using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Collections;


namespace MapEditor
{
    public class Soldier
    {

        public SoldierImage SoldierImage;

        public bool OrderCompleted;

        public bool NewOrder;


        //pathfinding
        private ArrayList myTargetPoints;

#region Soldier Location & facing
        public Point SoldierLocation
        {
            get { return new Point(X, Y); }
            set
            {
                X = value.X;
                Y = value.Y;
            }
        }

        //properties use double for internal accuracy
        private double _X;
        public int X
        {
            get { return (int)_X; }
            set { _X = (Double)value; }

        }
        private double _Y;
        public int Y
        {
            get { return (int)_Y; }
            set { _Y = (Double)value; }

        }

        private double _Facing;
        public int Facing
        {
            get { return (int)_Facing; }
            set { _Facing = (Double)value; }

        }

        private double _DefenseFacing;
        public int DefenseFacing
        {
            get { return (int)_DefenseFacing; }
            set { _DefenseFacing = (Double)value; }

        }
#endregion






        private DateTime LastThinkTime;
        private DateTime CurrentThinkTime;

        private double MovementRate; //per second
        private double TurnRate;     //per second

        private double CanTurn;
        private double CanMove;


        public Soldier()
        {
            //graphics part
            SoldierImage = new SoldierImage();
            //data part
            MovementRate = 50;//pixels per second
            TurnRate = 720;//degrees per second
        }

        public bool Create(int StartX, int StartY, int angle)
            //creates a new soldier
        {

            X = StartX;
            Y = StartY;

            Facing = angle;
            LastThinkTime = DateTime.Now;
            DefenseFacing = angle;


            return true;

        }

        public bool Think(Order myOrder)
        {

            //how long has it been since we last thought?
            CurrentThinkTime = DateTime.Now;
            int TimeElapsed = GetTimeElapsed();
            if (TimeElapsed == 0)
            {
                CanMove = 0;
                CanTurn = 0;
            }
            else
            {
                CanMove = MovementRate / (1000 / TimeElapsed);
                CanTurn = TurnRate / (1000 / TimeElapsed);
            }




            //if we haven't completed our current order, then do it!
            if (!OrderCompleted)
            {
                DoOrder(myOrder);
            }

            //update our latest think time
            LastThinkTime = DateTime.Now;
            
            return true;
        }


        private void DoOrder(Order myOrder)
        {
            if (myOrder.CurrentOrder == Order.OrderType.Hide)
            {
                DoHide();
            }

            if (myOrder.CurrentOrder == Order.OrderType.TurnToFace)
            {
                DoTurnToFace(myOrder);
            }

            if (myOrder.CurrentOrder == Order.OrderType.Move)
            {
                DoMove(myOrder);
            }
        }



        private bool ReachedTarget()
        {
            if (this.myTargetPoints.Count == 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private void ThisOrderIsCompleted()
        {
            myTargetPoints = null;
            OrderCompleted = true;
        }

        private void DoMove(Order myOrder)
        {
            if (this.NewOrder)
            {
                //calculate a path
                myTargetPoints = new ArrayList();
                myTargetPoints = AI.Path.Calculate(new Point(X, Y), new Point(myOrder.OrderPosition.X+this.SoldierImage.Center.X, myOrder.OrderPosition.Y+this.SoldierImage.Center.Y));

                this.NewOrder = false;
            }

            //if we're finished moving...
            if (ReachedTarget())
            {
                //turn to our defensive facing
                if (TurnToFace(DefenseFacing))
                {
                    ThisOrderIsCompleted();
                }
            }
            else
            {
                //otherwise move towards the target
                MoveToTarget();

            }
        }

        private bool TurnToFace(double NeededFacing)
        {
            return Movement.TurnTo(ref _Facing, NeededFacing, CanTurn);
        }

        private void MoveToTarget()
        {
            //turn to face the next waypoint
            double myNewAngle = MathUtils.GetAngle(new Point(X, Y), (Point)myTargetPoints[0]);

            if (Movement.TurnTo(ref _Facing,myNewAngle,CanTurn))
            {
                //and move to it
                double TotalDistanceMoved = 0;
                double DistanceMoved = 0;

                //keep cycling through the waypoints until we've moved our maximum
                while (TotalDistanceMoved < CanMove)
                {
                    if (!ReachedTarget())
                    {
                        if (Movement.MoveTo(ref _X, ref _Y, (Point)myTargetPoints[0], CanMove, ref DistanceMoved))
                        {
                            myTargetPoints.RemoveAt(0);
                        }
                        TotalDistanceMoved += DistanceMoved;
                    }
                    else
                    {
                        break;
                    }

                }

            }
        }


        private void DoTurnToFace(Order myOrder)
        {
            DefenseFacing = (int)MathUtils.GetAngle(new Point(X, Y), myOrder.OrderPosition);
            if (TurnToFace(DefenseFacing))
            {
                ThisOrderIsCompleted();
            }
        }

        private void DoHide()
            //do nothing for the moment
        {
            ThisOrderIsCompleted();
        }

        private int GetTimeElapsed()
        {
            //how many milliseconds since last think time?
            TimeSpan diff = (CurrentThinkTime - LastThinkTime);
            int ret =  diff.Milliseconds;
            return ret;
        }

        



        
        


    } //class soldier

}

